package com.zhangjunkai.load
{
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.LoaderInfo;
	import flash.events.Event;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLRequest;
	import flash.net.URLStream;
	import flash.utils.ByteArray;

	/**
	 * ProgressiveLoader 类用于下载渐进式图片 实际效果为下载时图片是模糊的 然后渐渐的会清晰起来<BR/>
	 * 下载的图片需为渐进式格式的 <code>JPG</code> 类型的图片 <BR/>
	 * 在PS中具体导出时  [格式选项]选择[连续]
	 * @author ZJK
	 */
	public class ProgressiveLoader extends Bitmap
	{
		private var _bufferLoader:Loader; //用于显示缓冲中的图片的 loader 对象
		private var _completeloader:Loader; //用于显示最终加载完成的图片

		private var _stream:URLStream; //载入流对象
		private var _bytes:ByteArray; //记录载入的字节对象

		private var _autoClear:Boolean; //是否自动清理事件

		/**
		 * 创建一个 <code>ProgressiveLoader</code> 对象
		 * @param request 加载对象
		 * @param autoClear 加载完成后 是否自动清理事件(默认值=true 仅清理事件 加载的数据将得到保留 此后将不能使用load()方法)
		 *
		 * 如果对autoClear不赋值false(默认是true) 则再次对ProgressiveLoader使用load()方法时将报错
		 * 如果要完全销毁本对象 应该调用closed()方法
		 * closed()方法调用将销毁所有事件监听 和已加载的数据 ProgressiveLoader对象将不再有用
		 */
		public function ProgressiveLoader(request:URLRequest, autoClear:Boolean=true)
		{
			_autoClear=autoClear;

			_bytes=new ByteArray();

			_bufferLoader=new Loader();
			_bufferLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onDrawBufferPicture);

			_completeloader=new Loader();
			_completeloader.contentLoaderInfo.addEventListener(Event.COMPLETE, onDrawCompletePicture);

			_stream=new URLStream();
			_stream.addEventListener(Event.OPEN, onOpen);
			_stream.addEventListener(ProgressEvent.PROGRESS, onLoading);
			_stream.addEventListener(Event.COMPLETE, onComplete);
			_stream.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus);
			_stream.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
			_stream.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);

			_stream.load(request);
		}

		/**
		 * 再次加载新的内容
		 * @param request URLRequest对象
		 * @throws Error autoClear=true时无法再次加载内容(ProgressiveLoader构造函数中设置)
		 */
		public function load(request:URLRequest):void
		{
			if (_autoClear)
			{
				throw new Error('构造函数中设置了自动清理 无法再次加载内容');
			}
			else
			{
				if (_stream.connected)
				{
					_stream.close();
				}
				_bufferLoader.unload();
				_completeloader.unload();
				_bytes=null;
				_bytes=new ByteArray();
				_stream.load(request);
			}
		}

		/**
		 * 删除所有的事件监听
		 */
		private function removeEventHandler():void
		{
			_stream.removeEventListener(Event.OPEN, onOpen);
			_stream.removeEventListener(ProgressEvent.PROGRESS, onLoading);
			_stream.removeEventListener(Event.COMPLETE, onComplete);
			_stream.removeEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus);
			_stream.removeEventListener(IOErrorEvent.IO_ERROR, onIoError);
			_stream.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);

			_bufferLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onDrawBufferPicture);
			_completeloader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onDrawCompletePicture);
		}

		/**
		 * 卸载掉加载的图片并且完全销毁
		 */
		public function closed():void
		{
			removeEventHandler();
			if (_stream != null)
			{
				if (_stream.connected)
				{
					_stream.close();
				}
				_stream=null;
			}
			if (_bufferLoader != null)
			{
				_bufferLoader.unload();
				_bufferLoader=null;
			}
			if (_completeloader != null)
			{
				_completeloader.unload();
				_bufferLoader=null;
			}
			_bytes=null;
			super.bitmapData.dispose();
			super.bitmapData=null;
		}

		/**
		 * 加载过程中的处理
		 * @param event
		 */
		private function onLoading(event:ProgressEvent):void
		{
			if (_stream.bytesAvailable > 0)
			{
				_stream.readBytes(_bytes, _bytes.length);
			}
			if (_bytes.length > 0)
			{
				_bufferLoader.loadBytes(_bytes);
			}
			dispatchEvent(event);
		}

		/**
		 * 图片加载过程中 流的处理
		 * @param event
		 */
		private function onDrawBufferPicture(event:Event):void
		{
			super.bitmapData=((event.target as LoaderInfo).content as Bitmap).bitmapData;
		}

		/**
		 * 图片完全加载完毕
		 * @param event
		 */
		private function onComplete(event:Event):void
		{
			if (_stream.bytesAvailable > 0)
			{
				_stream.readBytes(_bytes, _bytes.length);
			}
			if (_bytes.length > 0)
			{
				_completeloader.loadBytes(_bytes);
			}
			dispatchEvent(event);
		}

		/**
		 * 第二个load 将临时load中的数据加载完毕后
		 * @param event
		 */
		private function onDrawCompletePicture(event:Event):void
		{
			super.bitmapData=((event.target as LoaderInfo).content as Bitmap).bitmapData;
			if (_autoClear)
			{
				removeEventHandler();
			}
		}

		private function onOpen(event:Event):void
		{
			dispatchEvent(event);
		}

		private function onHttpStatus(event:HTTPStatusEvent):void
		{
			dispatchEvent(event);
		}

		private function onIoError(event:IOErrorEvent):void
		{
			dispatchEvent(event);
		}

		private function onSecurityError(event:SecurityErrorEvent):void
		{
			dispatchEvent(event);
		}
	}
}


